// pages/j/j.js
Page({

    /**
     * 页面的初始数据
     */
    data: {

    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function(options) {

    },

    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    onReady: function() {

    },

    /**
     * 生命周期函数--监听页面显示
     */
    onShow: function() {
        // this.forOfIteratorForOf();
        // this.newPromise();
        // this.asyncPromiseTwo();
        // this.normalPromiseTwo();
        // this.setTestTwo();
        // this.testRest();
        // this.testRaw();
        // this.objectCopy();
        // this.showModalTest();
    },

    showModalTest(){
        wx.showModal({
            title: '11',
            content: '11',
            confirmText:'取消',
            showConfirm:false,
            showCancel:false,
        })
    },

    // arguments变量的写法
    sortNumbers() {
        return Array.prototype.slice.call(arguments).sort();
    },
    // rest参数的写法
    sortNumbersRest(...numbers) {
        return numbers.sort();
    },
    // 下面是一个利用 rest 参数改写数组 push 方法的例子
    pushRest(array, ...items) {
        items.forEach((item) => {
            array.push(item);
        });
    },

    testRest() {
        var arr = [8, 3, 1, 6];
        // arguments变量的写法
        var arr2 = Array.prototype.slice.call(arr).sort();
        console.warn(arr); //[8, 3, 1, 6]
        console.warn(arr2); //[1, 3, 6, 8]
        // rest参数的写法
        var arr3 = [...arr.sort()]
        console.warn(arr3); //[1, 3, 6, 8]
    },

    //用来获取一个模板字符串的原始字符串的，
    // 比如说，占位符（例如 ${foo}）会被处理为它所代表的其他字符串，而转义字符（例如 \n）不会。
    testRaw() {
        console.warn(String.raw `Hi\n${2 + 3}!`);
        // 'Hi\n5!'，Hi 后面的字符不是换行符，\ 和 n 是两个不同的字符
        // 但是为了模拟 `t${0}e${1}s${2}t` 你可以这样做:
        console.warn(String.raw({
            raw: 'test'
        }, 0, 1, 2)); // 't0e1s2t'
    },

    //对象浅拷贝
    objectCopy() {
        let obj = {
            name: 'age',
            age: 23,
        };
        let obj2 = {...obj};
        console.log(obj2);
    },


    // // rest参数
    // var arr = this.sortNumbersRest(8, 3, 1, 6);
    // console.warn(arr) //[1, 3, 6, 8]
    //     // 下面是一个利用 rest 参数改写数组 push 方法的例子
    //     var a = [];
    // this.pushRest(a, 1, 2, 3);
    // console.warn(a); //[1, 2, 3]

    // // 下面是 rest 参数与箭头函数结合的例子
    // const numbers = (...nums) => nums.sort();
    // console.warn(numbers(1, 3, 2, 4)); //[1, 2, 3, 4]

    setTestTwo() {
        var arr1 = [1, 2, 3];
        var arr2 = [4, 3, 2];
        var set1 = new Set(arr1);
        var set2 = new Set(arr2);
        // 并集
        var union = new Set([...set1, ...set2]);
        console.warn(union); // {1, 2, 3, 4}
        // 交集
        var common = new Set([...set1].filter(value => set2.has(value)));
        console.warn(common); // {2, 3}
        //set1特有的元素,不同的元素
        var difference = new Set([...set1].filter(value => !set2.has(value)));
        console.warn(difference); // {1}
    },

    setTest() {
        // 去除数组重复成员
        var arr = [1, 1, 2, 3];
        var arr1 = Array.from(new Set(arr));
        console.warn(arr1); // [1, 2, 3]
        //扩展运算符和 Set 结构相结合，就可以去除数组的重复成员
        var arr2 = [...new Set(arr)];
        console.warn(arr2); // [1, 2, 3]

        // 在遍历操作中，同步改变原来的 Set 结构
        // 一种是利用原 Set 结构映射出一个新的结构，然后赋值给原来的 Set 结构
        var set = new Set([1, 2, 3]);
        set = new Set([...set].map(val => val * 2));
        // 另一种是利用 Array.from
        var set = new Set([1, 2, 3]);
        set = new Set(Array.from(set, val => val * 2));

        //数组的 map 和 filter 方法也可以用于 Set 了
        var set = new Set([1, 2, 3]);
        set = new Set([...set].map(x => x * 2));
        console.warn(set); //{2, 4, 6}
        var set = new Set([1, 2, 3, 4, 5]);
        set = new Set([...set].filter(x => (x % 2 == 0)));
        console.warn(set); //{2, 4}
        // 因此使用 Set 可以很容易地实现并集（Union）、交集（Intersect）和差集（Difference）。
        var a = new Set([1, 2, 3]);
        var b = new Set([4, 3, 2]);
        // 并集
        var union = new Set([...a, ...b]); // {1, 2, 3, 4}
        // 交集
        var intersect = new Set([...a].filter(x => b.has(x)))
        console.warn(intersect); // {2, 3}
        var difference = new Set([...a].filter(x => !b.has(x)))
        console.warn(difference); // {1}

        // forEach依次为键值、键名、Set 结构的键名就是键值（两者是同一个值）
        set.forEach((value, key) => console.warn(key + ':' + value))
        // 1 : 1
        // 4 : 4
        // 9 : 9
    },

    forOfIteratorForOf() {
        let es6 = {
            edition: 6,
            committee: "TC39",
            standard: "ECMA-262"
        };
        for (let e in es6) {
            console.log(e);
            break;
        }
        // edition
        // committee
        // standard

        // for (let e of es6) {
        //     console.log(e);
        // }
        // TypeError: es6[Symbol.iterator] is not a function
        // 上面代码表示，对于普通的对象， for...in 循环可以遍历键名， for...of 循环会报错。

        // 1一种解决方法是，使用 Object.keys 方法将对象的键名生成一个数组，然后遍历这个数组。
        for (var key of Object.keys(es6)) {
            console.log(key + ':' + es6[key]);
        }

        // for...of 循环相比上面几种做法，有一些显著的优点
        // 有着同 for...in 一样的简洁语法，但是没有 for...in 那些缺点。
        // 不同于 forEach 方法，它可以与 break 、 continue 和 return 配合使用。
        // 提供了遍历所有数据结构的统一操作接口。

        var arr = [1, 3, 5, 7, 9];
        arr.forEach((item, index, arr) => {
            // console.warn(item,index,arr);
            // break;
        });
    },

    //promise带捕获异常
    newPromise() {
        new Promise((resolve, reject) => {
            // var x=6;
            // 下面一行会报错，因为x没有声明
            resolve(x + 2);
        }).catch((error) => {
            // 捕获处理 Promise 内部发生的错误
            console.warn(error);
        }).then((res) => {
            console.warn("res");
            console.warn(res);
            y + 2;
        }).catch((error) => {
            // 第二个 catch 方法用来捕获，前一个 then 方法抛出的错误
            console.warn(error);
        });
    },

    testPromise() {
        // 回一个 Promise 对象，如果该对象状态变为 resolved ，则会调用 then 方法指定的回调函数；
        // 如果异步操作抛出错误，状态就会变为 rejected ，就会调用 catch 方法指定的回调函数，处理这个错误。另外， then 方法指定的回调函数，如果运行中抛出错误，也会被 catch 方法捕获。
        var promise = new Promise(function(resolve, reject) {
            throw new Error('test');
        });
        promise.catch(function(error) {
            console.log(error);
        });
        //，可以发现 reject 方法的作用，等同于抛出错误
        var promise = new Promise(function(resolve, reject) {
            try {
                throw new Error('test two');
            } catch (e) {
                reject(e);
            }
        });
        promise.catch(function(error) {
            console.log(error);
        })

        //一般总是建议，Promise 对象后面要跟 catch 方法，这样可以处理 Promise 内部发生的错误。 catch 方法返回的还是一个 Promise 对象，因此后面还可以接着调用 then 方法。
        var someAsyncThing = function() {
            return new Promise(function(resolve, reject) {
                // 下面一行会报错，因为x没有声明
                resolve(x + 2);
            })
        };
        someAsyncThing()
            .catch(function(error) {
                console.log('oh no', error);
            })
            .then(function() {
                console.log('carry on');
            })
        // oh no [ReferenceError: x is not defined]
        // carry on
        // 上面代码运行完 catch 方法指定的回调函数，会接着运行后面那个 then 方法指定的回调函数。如果没有报错，则会跳过 catch 方法
        var someAsyncThing = function() {
            return new Promise(function(resolve, reject) {
                // 下面一行会报错，因为x没有声明
                resolve();
            })
        };
        // catch 方法之中，还能再抛出错误。
        someAsyncThing()
            .catch(function(error) {
                console.log('oh no', error);
            })
            .then(function() {
                console.log('carry on');
                y + 2;
            }).catch(function(error) {
                console.log('carry on', error);
            });
        // carry on
        // 上面代码中，第二个 catch 方法用来捕获，前一个 catch 方法抛出的错误。
    },
    normalPromise() {
        // 写法有一个缺点，就是如果 f 是同步函数，那么它会在本轮事件循环的末尾执行
        var f = () => console.log('now');
        Promise.resolve().then(f);
        console.log('next');
        // next
        // now
    },

    //有一种方法，让同步函数同步执行，异步函数异步执行，并且让它们具有统一的 API 呢？回答是可以的，并且还有两种写法。第一种写法是用async 函数来写。
    asyncPromise() {
        var f = () => console.log('now');
        (async() => f())()
        .then();
        console.log('next');
        // now
        // next
    },

    normalPromiseTwo() {
        var f = () => {
            console.log('one');
        };
        Promise.resolve().then(f);
        console.log('two');
    },

    asyncPromiseTwo() {
        // 同步函数同步执行
        var f = () => {
            console.log('one');
        };
        (async() => {
            f();
        })().then();
        console.log('two');
        //one
        //two
    },

    /**
     * 生命周期函数--监听页面隐藏
     */
    onHide: function() {

    },

    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload: function() {

    },

    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh: function() {

    },

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom: function() {

    },

    /**
     * 用户点击右上角分享
     */
    onShareAppMessage: function() {

    }
})